#include "tamagawa.h"

/*
    The structure ofCRC field is shown .


  Strueture of CRC Field 10 bits
Startbit rc0 rc1 rc2 rc3 rc4 rc5 rc6 rc7 Delimiter
CRC code (LSB first)

(1)Start bit: Fixed.
(2)CRC code: This code conforms to the equation of G(X)= X^8 + 1 (X=rc0~rc7)
The data is arranged in LSB first.
The code is calculated from all bits without Start bit and Delimiter, of all fieldsexcept CRC field.
(3)Delimiter: Fixed
*/
#if 0
uint8_t CRC8(uint8_t *data, uint16_t datalen)
{
    unsigned char wCRCin = 0x00;
    unsigned char wCPoly = 0x01;

    while (datalen--)
    {
        wCRCin ^= *(data++);
        for (int i = 0; i < 8; i++)
        {
            if (wCRCin & 0x80)
                wCRCin = (wCRCin << 1) ^ wCPoly;
            else
                wCRCin = wCRCin << 1;
        }
    }
    return (wCRCin);
}
#else
uint8_t CRC8(uint8_t *buf, uint16_t len)
{
    uint8_t a, *p = buf;
    a = *p++;
    while (--len)
    {
        a ^= *p++;
    }
    return a;
}
#endif
int32_t tamagawa_encoder_process(uint8_t *buf, uint8_t len, tamagawa_encoder_data_struct_type *p)
{
    tamagawa_response_frame_struct_type *presp = (tamagawa_response_frame_struct_type *)buf;
    if (len < 3)
        return -1;
    if (CRC8(buf, len - 1) == buf[len - 1])
    {
        switch (presp->frame[0])
        {
        case DataReadOut_ID0:
            if (6 == len)
            {
                p->sf.data = presp->Data_ID0.sf.data;
                p->abs = *(uint32_t *)&presp->Data_ID0.abs[0] & 0x00FFFFFF;
            }
            else
            {
                return -4;
            }
            break;
        case DataReadOut_ID1:
            if (6 == len)
            {
                p->sf.data = presp->Data_ID1.sf.data;
                p->abm = *(uint32_t *)&presp->Data_ID1.abm[0] & 0x00FFFFFF;
            }
            else
            {
                return -4;
            }
            break;
        case DataReadOut_ID2:
            if (4 == len)
            {
                p->sf.data = presp->Data_ID2.sf.data;
                p->enid = presp->Data_ID2.enid;
            }
            else
            {
                return -4;
            }
            break;
        case DataReadOut_ID3:
            if (11 == len)
            {
                p->sf.data = presp->Data_ID0.sf.data;
                p->enid = presp->Data_ID3.enid;
                p->almc = presp->Data_ID3.almc;
                p->abs = *(uint32_t *)&presp->Data_ID3.abs[0] & 0x00FFFFFF;
                p->abm = *(uint32_t *)&presp->Data_ID3.abm[0] & 0x00FFFFFF;
            }
            else
            {
                return -4;
            }
            break;
        case WriteToEEPROM_ID6:
            // TO DO
            break;
        case ReadOutFromEEPROM_IDD:
            // TO DO
            break;
        case Reset_ID7:
        case Reset_ID8:
        case Reset_IDC:
            // TO DO
            break;
        default:
            return -3;
        }
        buf[0] = 0;
    }
    else
    {
        return -2;
    }
    return 0;
}
